package com.tcxhb.job.core.service.job.impl;

import com.tcxhb.job.dao.dataobject.JobInfoDO;
import com.tcxhb.job.dao.dataobject.query.JobInfoQuery;
import com.tcxhb.job.dao.dataobject.query.JobScanQuery;
import com.tcxhb.job.dao.repository.JobInfoRepository;
import com.tcxhb.job.core.service.job.JobInfoService;
import com.tcxhb.job.common.constants.enums.JobStatusEnum;
import com.tcxhb.job.common.constants.enums.ScheduleTypeEnum;
import com.tcxhb.job.common.model.PageResponse;
import com.tcxhb.job.common.model.job.ScheduleConf;
import com.tcxhb.job.common.utils.ParamUtils;
import com.tcxhb.job.core.utils.SchedulerTimeUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * author:auto.generator
 * time: 2023-11-02
 */
@Service
public class JobInfoServiceImpl implements JobInfoService {
    @Resource
    private JobInfoRepository repository;

    @Override
    public Long create(JobInfoDO wjJob) {
        //修改执行时间
        Long time = SchedulerTimeUtils.nextSchedulerTime(wjJob, new Date());
        wjJob.setNextTime(time);
        return repository.create(wjJob);
    }

    @Override
    public boolean deleteById(Long id) {
        ParamUtils.notNull(id, "id不能为空");
        return repository.deleteById(id);
    }

    @Override
    public boolean updateById(JobInfoDO update) {
        JobInfoDO exit = queryById(update.getId());
        update = buildUpdateDO(update, exit);
        return repository.updateById(update);
    }

    @Override
    public Map<Long, JobInfoDO> queryByIds(List<Long> ids) {
        JobInfoQuery query = new JobInfoQuery();
        query.setIds(ids);
        List<JobInfoDO> list = list(query);
        if (CollectionUtils.isEmpty(list)) {
            return new HashMap<>();
        }
        return list.stream().collect(Collectors.toMap(m -> m.getId(), m -> m));
    }

    private JobInfoDO buildUpdateDO(JobInfoDO update, JobInfoDO exit) {
        //更新设置
        //更新下一次执行时间
        if (ScheduleTypeEnum.Cron.eq(exit.getScheduleType())) {
            ScheduleConf conf = update.getScheduleConf();
            if (conf == null || StringUtils.isBlank(conf.getCron())) {
                return update;
            }
            //定时配置不为空
            if (!conf.getCron().equals(exit.getScheduleConf().getCron())) {
                Long time = SchedulerTimeUtils.nextSchedulerTime(update, new Date());
                update.setNextTime(time);
            }
        }
        return update;
    }

    @Override
    public JobInfoDO queryById(Long id) {
        ParamUtils.notNull(id, "id不能为空");
        return repository.queryById(id);
    }

    @Override
    public PageResponse<JobInfoDO> page(JobInfoQuery query) {
        return repository.page(query);
    }

    @Override
    public List<JobInfoDO> list(JobInfoQuery query) {
        return repository.list(query);
    }

    @Override
    public List<JobInfoDO> scan(Long lastId, Long startTime, Integer pageSize) {
        ParamUtils.notNull(startTime, "startTime is null");
        JobScanQuery query = new JobScanQuery();
        query.setLastId(lastId);
        query.setStartTime(startTime);
        query.setLimit(pageSize);
        return repository.scan(query);
    }

    @Override
    public Boolean start(Long id) {
        JobInfoDO exit = queryById(id);
        if (JobStatusEnum.start.eq(exit.getStatus())) {
            return true;
        }
        JobInfoDO update = new JobInfoDO();
        Long time = SchedulerTimeUtils.nextSchedulerTime(exit, new Date());
        update.setNextTime(time);
        update.setId(id);
        update.setStatus(JobStatusEnum.start.getType());
        return repository.updateById(update);
    }

    @Override
    public boolean freshNextScheduleTime(JobInfoDO old, Long nextTime) {
        ParamUtils.notNull(old.getNextTime(), "nextTime");
        JobInfoDO update = new JobInfoDO();
        update.setId(old.getId());
        update.setNextTime(nextTime);
        update.setLastTime(old.getNextTime());
        return repository.freshNextTime(update);
    }

}
